const dotenv = require('dotenv');
dotenv.config(); // 加载环境变量
const mongoose = require("mongoose");
const { User, SettledUser, UserSwiper, dynamics, OrdersSchema, Follow } = require('../models/User');
const bcrypt = require('bcryptjs');
const crypto = require('crypto');
const jwt = require('jsonwebtoken');
const { isValidObjectId } = require('mongoose');
const { sendResponse, sendError } = require('../utils/response');

//用户登录方法err返回错误信息，req浏览器发出的请求对象 res服务端返回的响应对象，next将控制传递给下一个中间件
exports.loginUser = async (req, res, next) => {
    try {
        const { account, password, code } = req.body;

        if (!account || !password || !code) {
            throw new Error('信息不能为空！');
        }

        const user = await User.findOne({ account });
        //存在就直接生成token返回token信息,不存在添加进数据库新增用户
        if (user) {
            //用户的密码，数据库用户的密码进行对比
            const passWordNew = await bcrypt.compare(password, user.password);
            if (passWordNew) {
                sendResponse(res, {
                    userid: user._id,
                    account: user.account,
                    role: user.role,
                    userType: user.userType,
                    token: await jwt.sign({ id: user._id }, process.env.JWT_SECRET, {
                        expiresIn: process.env.JWT_EXPIRES_IN
                    }),
                }, 200, '登录成功！');
            } else {
                throw new Error('密码输入错误！');
            }
        } else {
            //如果用户没有存在在数据库就直接创建一个用户 
            //数值越大越安全但也越慢也就是加密强度
            const salt = await bcrypt.genSalt(10);
            //保存到数据库
            const createUser = await User.create({
                account,
                role: 'user',
                password: await bcrypt.hash(password, salt),//密码加密
                username: `用户${Date.now()}${Math.floor(1000 + Math.random() * 9000)}`
            });

            if (createUser) {
                sendResponse(res, {
                    userid: createUser.id,
                    account: account,
                    role: 'user',
                    userType: 0,
                    token: await jwt.sign({ id: createUser.id }, process.env.JWT_SECRET, {
                        expiresIn: process.env.JWT_EXPIRES_IN || '24h' // 设置过期时间
                    }),
                }, 200, '注册成功！');
            } else {
                throw new Error('服务器错误！');
            }
        }

    } catch (error) {
        sendError(res, error.message, 400);
        console.log('有错误！:', error);
    }
}

//获取用户信息 获取token并验证有效性 然后返回对应用户信息
exports.getUserinfo = async (req, res, next) => {
    try {
        getTokenCheck(req, res);

        const token = await jwt.verify(req.headers.authorization.split(' ')[1], process.env.JWT_SECRET);

        const user = await User.findOne({ _id: token.id });
        if (!user) {
            return sendError(res, 'token解析用户信息失败！', 430);
        }

        const post = await SettledUser.findOne({ userid: user._id });

        if (!post) {
            await User.updateOne({ _id: token.id }, {
                'userType': 0
            })
        }

        sendResponse(res, {
            username: post ? post.realName : user.username,
            userid: user.id,
            account: user.account,
            role: user.role,
            userType: user.userType,
            avatar: post ? post.avatar : user.avatar,
            gender: post ? post.gender : '',
            age: post ? post.age : '',
            personalIntro: post ? post.personalIntro : '',
            lifePhotos: post ? post.lifePhotos : [],
            address: post ? post.address : '',
            followNumbers: await Follow.countDocuments({ follower: user.id }),//关注的人数
            followingNumbers: await Follow.countDocuments({ following: user.id }),//粉丝人数
            dynamicNumbers: await dynamics.countDocuments({ userid: user.id }),//发布的动态数量
            SettledUserid: post ? post._id : '',//搭子id
        }, 200, '解析成功！');
    } catch (error) {
        sendError(res, error.message, 400);
        console.log('有错误！:', error);
    }
}

//搭子入驻
exports.Settled = async (req, res, next) => {
    try {
        getTokenCheck(req, res);

        const { realName, age, phone, gender, idNumber, idCardFront, idCardBack,
            lifePhotos, voiceUrl, personalIntro, avatar, address, tag
        } = req.body;

        if (!realName || !age || !gender || !idNumber || !idCardFront || !idCardBack,
            !lifePhotos || !personalIntro || !avatar || !address || !tag) {
            throw new Error('入驻信息不能为空！');
        }

        const token = await jwt.verify(req.headers.authorization.split(' ')[1], process.env.JWT_SECRET);

        const getUserId = await User.findOne({ _id: token.id })

        if (!getUserId) {
            throw new Error('用户不存在！');
        }

        //通过token解密拿到用户id然后到搭子表里面查是否申请过搭子如果申请过直接提示
        const SettledUserId = await SettledUser.findOne({ userid: getUserId._id })

        if (SettledUserId) {
            throw new Error('您已提交过入驻申请！');
        }

        const user = await SettledUser.create({
            userid: getUserId._id,
            realName: realName || '',
            age: age || '',
            phone: phone || '',
            gender: gender || '',
            idNumber: idNumber || '',
            idCardFront: idCardFront || '',
            idCardBack: idCardBack || '',
            lifePhotos: lifePhotos || '',
            voiceUrl: voiceUrl || '',
            personalIntro: personalIntro || '',
            avatar: avatar || '',
            address: address || '',
            tag: tag || '',
            partnerAudit: {
                status: 'pending'
            }
        });

        if (!user) {
            throw new Error('提交失败！');
        }

        sendResponse(res, null, 200, '提交成功！');

    } catch (error) {
        sendError(res, error.message, 400);
    }
}

//编辑用户信息
exports.editUserInfo = async (req, res) => {
    try {
        getTokenCheck(req, res);

        const token = await jwt.verify(req.headers.authorization.split(' ')[1], process.env.JWT_SECRET);

        const getUserId = await User.findOne({ _id: token.id })

        if (!getUserId) {
            throw new Error('用户不存在！');
        }

        const { avatar, age, username, gender, address, personalIntro, lifePhotos } = req.body;

        if (!avatar || !age || !username || !gender || !address || !personalIntro || !lifePhotos) {
            throw new Error('请确保编辑信息都已填写！');
        }

        const UpdateUser = await User.updateOne({ _id: getUserId._id }, {
            'username': username || '',
            'avatar': avatar || '',
        });

        const UpdateSettledUser = await SettledUser.updateOne({ userid: getUserId._id }, {
            avatar,
            address,
            gender,
            age,
            personalIntro,
            lifePhotos
        });

        if (!UpdateSettledUser && !UpdateUser) {
            throw new Error('数据编辑失败！');
        }

        sendResponse(res, null, 200, '操作成功！');
    } catch (error) {
        sendError(res, error.message, 400);
    }
}

//搭子列表可通过pending approved rejected进行查询默认获取审核通过搭子
exports.getSettledLists = async (req, res, next) => {
    try {
        // 1. 参数处理（带默认值）
        const page = Math.max(1, parseInt(req.query.page) || 1); // 最小第1页
        const size = Math.min(100, parseInt(req.query.pageSize) || 10); // 最大100条
        const status = req.query.status || 'approved';//审核状态

        // 1. 安全处理关键词（防止正则注入）
        const sanitize = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
        const safeKeyword = sanitize(status);

        //因为数据库查询返回的是数组，而数组没有clone方法所以延迟执行
        const user = SettledUser.find({ 'partnerAudit.status': safeKeyword });

        // 2. 核心计算
        const skip = (page - 1) * size;
        const [total, data] = await Promise.all([
            SettledUser.countDocuments({ 'partnerAudit.status': status }),      // 获取总数
            user.skip((page - 1) * size).limit(size).lean().exec() // 显式执行查询
        ]);

        sendResponse(res, {
            page,
            size,
            total,
            totalPages: Math.ceil(total / size),
            data: data ? data : []
        }, 200, '操作成功！');
    } catch (error) {
        sendError(res, error.message, 400);
    }
}

//轮播图列表
exports.Swipers = async (req, res) => {
    try {
        const getSwipers = await UserSwiper.find({});

        if (getSwipers) {
            sendResponse(res, getSwipers, 200, '返回成功！');
        } else {
            sendResponse(res, null, 200, '暂无数据！');
        }
    } catch (error) {
        sendError(res, error.message, 400);
    }
}

//发布动态
exports.Newdynamics = async (req, res) => {
    try {
        getTokenCheck(req, res);

        const token = await jwt.verify(req.headers.authorization.split(' ')[1], process.env.JWT_SECRET);

        const getUserId = await User.findOne({ _id: token.id })

        if (!getUserId) {
            throw new Error('用户不存在！');
        }

        const { title, coverImage, describe, links, tags } = req.body;

        if (!title || !coverImage || !describe || !links || !tags) {
            throw new Error('发布动态信息不能为空！');
        }

        if (title.length > 30) {
            throw new Error('标题长度需在1-30字符之间！');
        }

        if (describe.length > 200) {
            throw new Error('内容长度需在1-200字符之间！');
        }

        const adddynamics = await dynamics.create({
            title, coverImage, describe, links, tags,
            userid: token.id,
            partnerAudit: {
                status: 'pending'
            }
        });

        if (!adddynamics) {
            throw new Error('动态发布失败！');
        }

        sendResponse(res, null, 200, '操作成功！');
    } catch (error) {
        sendError(res, error.message, 400);
    }
}

//获取用户动态详情
exports.userDynamicsDetails = async (req, res) => {
    try {
        getTokenCheck(req, res);

        const id = req.query.id;

        if (!id) {
            throw new Error('id不能为空！');
        }

        const result = await dynamics.findOne({ _id: id })
            .populate('userid', 'username avatar')  // 关键！自动关联用户信息
            .lean() // 关键！转换为纯对象
            .transform(doc => {
                if (!doc) throw new Error('动态不存在');

                // 结构化处理
                return {
                    ...doc,
                    userinfo: {
                        username: doc.userid?.username || '',
                        avatar: doc.userid?.avatar || '',
                        id: doc.userid?._id.toString() || ''
                    }
                }
            });

        sendResponse(res, result, 200, '操作成功！');
    } catch (error) {
        sendError(res, error.message, 400);
    }
}

//通过id获取搭子详情
exports.getSettledUserDetails = async (req, res) => {
    try {
        getTokenCheck(req, res);

        const id = req.query.id;

        if (!id) {
            throw new Error('id不能为空！');
        }

        const user = await SettledUser.findOne({ _id: id });

        if (!user) {
            throw new Error('id查无此用户！');
        }

        if (!user.partnerAudit.status == 'approved') {
            throw new Error('当前搭子未被审核通过！');
        }

        sendResponse(res, user, 200, '操作成功！');
    } catch (error) {
        sendError(res, error.message, 400);
    }
}

//通过用户id获取该用户发布的动态
exports.getUserDynamicsLists = async (req, res) => {
    try {
        getTokenCheck(req, res);

        // 1. 参数处理（带默认值）
        const page = Math.max(1, parseInt(req.query.page) || 1); // 最小第1页
        const size = Math.min(100, parseInt(req.query.pageSize) || 10); // 最大100条
        const id = req.query.userId;

        if (!id) {
            throw new Error('用户id不能为空！');
        }

        //因为数据库查询返回的是数组，而数组没有clone方法所以延迟执行
        const user = dynamics.find({ 'userid': id });

        // 2. 核心计算
        const skip = (page - 1) * size;
        const [total, data] = await Promise.all([
            dynamics.countDocuments({ 'userid': id }),      // 获取总数
            user.skip((page - 1) * size).limit(size).lean().exec() // 显式执行查询
        ]);

        sendResponse(res, {
            page,
            size,
            total,
            totalPages: Math.ceil(total / size),
            data: data ? data : []
        }, 200, '操作成功！');
    } catch (error) {
        sendError(res, error.message, 400);
    }
}

//订单创建 OrdersSchema
exports.OrderCreate = async (req, res) => {
    try {
        getTokenCheck(req, res);

        const token = await jwt.verify(req.headers.authorization.split(' ')[1], process.env.JWT_SECRET);

        const getUserId = await User.findOne({ _id: token.id })

        if (!getUserId) {
            throw new Error('用户不存在！');
        }

        // if (getUserId._id.equals(token.id)) {
        //     throw new Error('您不能给自己下单！');
        // }

        const { id, name, phone, wechat, meet_time, meet_name, meet_Matters, address } = req.body;

        if (!name || !phone || !wechat || !meet_time || !meet_name || !meet_Matters) {
            throw new Error('请确保所填信息不为空！');
        }

        const user = await SettledUser.findOne({ _id: id });

        if (!user) {
            throw new Error('该伴游用户不存在,请重新选择！');
        }

        const order = await OrdersSchema.create({
            // 系统生成字段
            buddy_id: id,
            user_id: token.id,
            order_id: generateSecureId(),
            buddy_name: user.realName,
            buddy_phone: maskPhone(user.phone),
            // 结构化嵌套文档
            meet_info: {
                contact: {
                    name: name,        // 使用对象结构替代点符号
                    phone: phone,
                    wechat: wechat
                },
                meet_time: meet_time,
                meet_place: {
                    name: meet_name,
                    address: address
                },
                meet_Matters: meet_Matters  // 直接赋值数组
            }
        });

        if (!order) {
            throw new Error('订单创建失败请稍后重试！');
        }

        sendResponse(res, null, 200, '操作成功！');
    } catch (error) {
        sendError(res, error.message, 400);
    }
}

//获取当前用户订单列表
exports.getOrderLists = async (req, res) => {
    try {
        getTokenCheck(req, res);

        const token = await jwt.verify(req.headers.authorization.split(' ')[1], process.env.JWT_SECRET);

        const getUserId = await User.findOne({ _id: token.id })

        if (!getUserId) {
            throw new Error('用户不存在！');
        }

        // 1. 参数处理（带默认值）
        const page = Math.max(1, parseInt(req.query.page) || 1); // 最小第1页
        const size = Math.min(100, parseInt(req.query.pageSize) || 10); // 最大100条

        //因为数据库查询返回的是数组，而数组没有clone方法所以延迟执行
        const user = OrdersSchema.find({ 'user_id': getUserId._id });

        // 2. 核心计算
        const skip = (page - 1) * size;
        const [total, data] = await Promise.all([
            OrdersSchema.countDocuments({ 'user_id': getUserId._id }),      // 获取总数
            user.skip((page - 1) * size).limit(size).lean().exec() // 显式执行查询
        ]);

        sendResponse(res, {
            page,
            size,
            total,
            totalPages: Math.ceil(total / size),
            data: data ? data : []
        }, 200, '操作成功！');
    } catch (error) {
        sendError(res, error.message, 400);
    }
}

//关注用户
exports.followUser = async (req, res) => {
    try {
        // Token 验证
        getTokenCheck(req, res);

        // 解析Token获取用户信息
        const token = await jwt.verify(
            req.headers.authorization.split(' ')[1],
            process.env.JWT_SECRET
        );

        // 查询关注发起者（更明确的变量名）
        const followerUser = await User.findById(token.id).select('_id');
        if (!followerUser) {
            throw new Error('用户不存在');
        }

        // 获取关注目标ID
        const { followingId } = req.body;

        // 参数完整性校验（增强版）
        if (!followingId || !isValidObjectId(followingId)) {
            throw new Error('参数格式不合法');
        }

        // 自关注校验（安全访问）
        if (followerUser._id.toString() === followingId.toString()) {
            throw new Error('禁止自关注');
        }

        // 创建关注关系
        const newFollow = await Follow.create({
            follower: followerUser._id,
            following: followingId
        });

        if (!newFollow) {
            throw new Error('关注关系创建失败');
        }

        sendResponse(res, null, 200, '操作成功');
    } catch (error) {
        sendError(res, error.message, 400);
    }
}

//取消关注
exports.unfollowUser = async (req, res) => {
    try {
        getTokenCheck(req, res);

        // 解析Token获取用户信息
        const token = await jwt.verify(
            req.headers.authorization.split(' ')[1],
            process.env.JWT_SECRET
        );

        // 查询关注发起者（更明确的变量名）
        const followerUser = await User.findById(token.id).select('_id');
        if (!followerUser) {
            throw new Error('用户不存在');
        }

        const { followingId } = req.body;

        // 根据id取消关注
        const Usercancel = await Follow.findOneAndDelete({
            follower: followerUser._id,
            following: followingId
        });

        if (!Usercancel) {
            throw new Error('取消关注失败！');
        }

        sendResponse(res, null, 200, '操作成功！');
    } catch (error) {
        sendError(res, error.message, 400);
    }
}

//关注列表
exports.getFollowingList = async (req, res) => {
    try {
        getTokenCheck(req, res);

        // 分页参数处理
        const page = Math.max(1, parseInt(req.query.page) || 1);
        const size = Math.min(100, parseInt(req.query.pageSize) || 10);
        const skip = (page - 1) * size;

        const { followerId } = req.query;

        // 并行查询
        const [total, data] = await Promise.all([
            Follow.countDocuments({ follower: followerId }), // 总记录数
            Follow.find({ follower: followerId })
                .populate('following', 'username avatar')
                .sort({ createdAt: -1 })
                .skip(skip)
                .limit(size)
                .lean()
        ]);

        sendResponse(res, {
            page,
            size,
            total,
            totalPages: Math.ceil(total / size),
            data: data ? data : []
        }, 200, '操作成功！');
    } catch (error) {
        sendError(res, error.message, 400);
    }
};

//粉丝列表
exports.getFollowerList = async (req, res) => {
    try {
        getTokenCheck(req, res);

        // 解析Token获取用户信息
        const currentUser = await jwt.verify(
            req.headers.authorization.split(' ')[1],
            process.env.JWT_SECRET
        );

        const currentUserId = new mongoose.Types.ObjectId(currentUser.id);

        // 分页参数处理
        const page = Math.max(1, parseInt(req.query.page) || 1);
        const size = Math.min(100, parseInt(req.query.pageSize) || 10);
        const skip = (page - 1) * size;

        // 目标用户ID（被查看者的ID）
        const { followingId } = req.query;

        // 参数验证
        if (!isValidObjectId(followingId)) {
            throw new Error('无效的用户ID');
        }

        const targetId = new mongoose.Types.ObjectId(followingId);

        // 聚合查询管道
        const pipeline = [
            // 基础匹配条件
            { $match: { following: targetId } },

            // 关联用户信息
            {
                $lookup: {
                    from: 'users',
                    localField: 'follower',
                    foreignField: '_id',
                    as: 'userInfo'
                }
            },
            { $unwind: '$userInfo' },

            // 检查当前用户是否关注该粉丝
            {
                $lookup: {
                    from: 'follows',
                    let: { targetId: '$follower' },
                    pipeline: [
                        {
                            $match: {
                                $expr: {
                                    $and: [
                                        { $eq: ['$follower', currentUserId] }, // 类型一致
                                        { $eq: ['$following', '$$targetId'] }
                                    ]
                                }
                            }
                        }
                    ],
                    as: 'followStatus'
                }
            },

            // 投影最终字段
            {
                $project: {
                    _id: 0,
                    userId: '$follower',
                    username: '$userInfo.username',
                    avatar: '$userInfo.avatar',
                    isFollowing: { $cond: [{ $gt: [{ $size: '$followStatus' }, 0] }, true, false] },
                    followedAt: '$createdAt'
                }
            },

            // 分页处理
            { $skip: skip },
            { $limit: size }
        ];

        // 执行并行查询
        const [total, data] = await Promise.all([
            // 保持类型一致
            Follow.countDocuments({ following: targetId }),
            Follow.aggregate(pipeline)
        ]);

        sendResponse(res, {
            page,
            size,
            total,
            totalPages: Math.ceil(total / size),
            data: data || []
        }, 200, '操作成功');

    } catch (error) {
        console.error('获取粉丝列表失败:', error);
        sendError(res, error.message, 500);
    }
};

//判断是否关注当前用户
exports.isFollow = async (req, res) => {
    try {
        getTokenCheck(req, res);

        // 解析Token获取用户信息
        const token = await jwt.verify(
            req.headers.authorization.split(' ')[1],
            process.env.JWT_SECRET
        );

        const currentUserId = token.id;
        const targetUserId = req.query.userId;

        // 参数有效性验证
        if (!isValidObjectId(targetUserId)) {
            throw new Error('无效的用户标识符');
        }

        // 关键判断逻辑
        const isSelf = currentUserId === targetUserId;

        // 如果是自己则直接返回
        if (isSelf) {
            return sendResponse(res, {
                isSelf: true,
                isFollowing: false,  // 自己不能关注自己
                timestamp: new Date().toISOString()
            }, 200, '操作成功！');
        }

        // 数据库查询关注状态
        const followRelation = await Follow.findOne({
            follower: new mongoose.Types.ObjectId(currentUserId),
            following: new mongoose.Types.ObjectId(targetUserId)
        }).lean();

        sendResponse(res, {
            isSelf: false,
            isFollowing: !!followRelation,
            timestamp: new Date().toISOString()
        }, 200, '操作成功！');
    } catch (error) {
        sendError(res, error.message, 400);
    }
}

//删除动态
exports.deletePost = async (req, res) => {
    try {
        getTokenCheck(req, res);

        // 身份验证
        const currentUser = await jwt.verify(
            req.headers.authorization.split(' ')[1],
            process.env.JWT_SECRET
        );

        // 参数验证
        const postId = req.query.id;
        if (!mongoose.isValidObjectId(postId)) {
            throw new Error('无效的瞬间ID');
        }

        // 查询目标动态
        const post = await dynamics.findById(postId).select('author').lean();
        if (!post) {
            return sendError(res, '动态不存在或已被删除', 404);
        }

        // 权限验证（关键逻辑）
        if (!post.author.equals(currentUser._id)) {
            return sendError(res, '您无权删除他人动态', 403);
        }

        // 执行删除
        const deletedPost = await dynamics.findByIdAndDelete(postId);

        if (!deletedPost) {
            throw new Error('删除失败，请稍后重试！');
        }

        sendResponse(res,
            { deletedId: deletedPost._id },
            200,
            '动态删除成功'
        );

    } catch (error) {
        console.error('删除动态失败:', error);
        sendError(res, error.message, error.statusCode || 500);
    }
};

//编辑动态
exports.editDynamics = async (req, res) => {
    try {
        getTokenCheck(req, res);

        // 验证用户身份
        const token = await jwt.verify(
            req.headers.authorization.split(' ')[1],
            process.env.JWT_SECRET
        );

        // 获取动态ID和更新内容
        const dynamicId = req.body.id;
        const { title, coverImage, describe, links, tags } = req.body;

        // 参数校验
        if (!mongoose.isValidObjectId(dynamicId)) {
            throw new Error('无效的动态ID');
        }

        if (!title || !coverImage || !describe || !links || !tags) {
            throw new Error('所有字段均为必填项');
        }

        if (title.length > 30) {
            throw new Error('标题长度需在1-30字符之间');
        }

        if (describe.length > 200) {
            throw new Error('内容长度需在1-200字符之间');
        }

        // 验证动态归属权
        const existingDynamic = await dynamics.findById(dynamicId);
        if (!existingDynamic) {
            throw new Error('动态不存在');
        }

        if (existingDynamic.userid.toString() !== token.id) {
            throw new Error('无权编辑他人动态');
        }

        // 执行更新操作
        const updatedDynamic = await dynamics.findByIdAndUpdate(
            dynamicId,
            {
                title,
                coverImage,
                describe,
                links,
                tags,
                $set: {
                    "partnerAudit.status": "pending", // 重置审核状态
                    updatedAt: new Date()
                }
            },
            { new: true, runValidators: true }
        );

        if (!updatedDynamic) {
            throw new Error('动态更新失败');
        }

        sendResponse(res, updatedDynamic, 200, '动态更新成功');
    } catch (error) {
        console.error('编辑动态失败:', error);
        sendError(res, error.message, 400);
    }
};

//token校验
const getTokenCheck = async (req, res) => {
    try {
        const headerstoken = req.headers.authorization;
        if (headerstoken.split(' ').lenght <= 1) {
            throw new Error('请求头无token！');
        }

        const token = await jwt.verify(headerstoken.split(' ')[1], process.env.JWT_SECRET);
        if (!token) {
            throw new Error('无效token！');
        }
    } catch (error) {
        sendError(res, error.message, 430);
    }
}

//手机号加密显示
const maskPhone = (phone) => {
    // 严谨格式校验
    if (!phone || typeof phone !== 'string' || !/^1[3-9]\d{9}$/.test(phone)) {
        return '***无效号码***';
    }

    return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
}

//订单号生成
const generateSecureId = () => {
    const timestamp = Date.now().toString();
    const random = crypto.randomBytes(4).toString('hex');
    const hash = crypto.createHash('sha1')
        .update(timestamp + random)
        .digest('hex')
        .substr(0, 10);
    return `DD${timestamp}${hash}`.toUpperCase();
}